package com.sunxueqi.framework.aspect;

import java.lang.reflect.Method;
import java.sql.Timestamp;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import com.sunxueqi.common.constant.StatusConstants;
import com.sunxueqi.common.utils.AddressUtils;
import com.sunxueqi.common.utils.IpUtils;
import com.sunxueqi.common.utils.KeyGenerate;
import com.sunxueqi.common.utils.SecurityUtils;
import com.sunxueqi.common.utils.ServletUtils;
import com.sunxueqi.framework.annotation.Log;
import com.sunxueqi.framework.annotation.VLog;
import com.sunxueqi.framework.manager.AsyncFactory;
import com.sunxueqi.project.log.vo.VisitLog;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.hutool.json.JSONUtil;

//使之成为切面类
@Aspect
@Component
public class VisitLogAspect {

	/**
	 * 定义切入点，切入点为使用了该注解的所有方法
	 */
	@Pointcut("@annotation(com.sunxueqi.framework.annotation.VLog)")
	public void logPointCut() {}
	
	/**
	 * 
	 * @throws Throwable 
	 */
	@AfterReturning("logPointCut()")
	public void doAfter(JoinPoint joinPoint) throws Throwable {
		handleVisitLog(joinPoint, null);
	}
	
	@AfterThrowing(value = "logPointCut()", throwing = "e")
	public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
		handleVisitLog(joinPoint, e);
	}
	
	protected void handleVisitLog(final JoinPoint joinPoint, final Exception e) {
		// 获取注解
		VLog vLog = getAnnotationLog(joinPoint);
		if(vLog == null) {
			return;
		}
		VisitLog visitLog = new VisitLog();
		visitLog.setId(KeyGenerate.getKeyId());
		String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
		String address = AddressUtils.getCityInfoByIp(ip);
		visitLog.setIp(ip);
		visitLog.setLocation(address);
		visitLog.setUrl(ServletUtils.getRequest().getRequestURI());
		if(e != null) {
			visitLog.setStatus(StatusConstants.FAILED);
			visitLog.setErrorMsg(StrUtil.subPre(e.getMessage(), 2000));
		} else {
			visitLog.setStatus(StatusConstants.SUCCESSFUL);
		}
		visitLog.setEntryUrl(ServletUtils.getRequest().getHeader("referer"));
		UserAgent usetAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
		visitLog.setBrowser(usetAgent.getBrowser().toString());
		visitLog.setOs(usetAgent.getOs().toString());
		visitLog.setDeleteStatus(StatusConstants.NORMAL);
		visitLog.setCreateTime(new Timestamp(System.currentTimeMillis()));
		visitLog.setCreateBy(SecurityUtils.getLoginUserId());
		
		// 获取注解中对方法的描述信息
		visitLog.setTitle(vLog.title());
		
		ThreadUtil.execAsync(AsyncFactory.recordVisitLog(visitLog));
		
	}
	
	
	/**
	 * 获取注解信息
	 * @param joinPoint
	 * @return
	 */
	private VLog getAnnotationLog(JoinPoint joinPoint) {
		Signature signature = joinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = methodSignature.getMethod();
		if(method != null) {
			return method.getAnnotation(VLog.class);
		}
		return null;
	}
	
}
